#include "pollscheduler.h"
#include "../utils/logger.h"
#include <QThread>
#include <QCoreApplication>

// ============================================================================
// BusPollerThread 实现
// ============================================================================

BusPollerThread::BusPollerThread(int busId, QSerialPort *serialPort,
                                 const QVector<Meter *> &meters, QObject *parent)
    : QThread(parent), m_busId(busId), m_serialPort(serialPort), m_modbusMaster(nullptr), m_meters(meters), m_pollInterval(500), m_running(false)
{
    // 初始化所有电表的采样时间为当前时间
    QDateTime now = QDateTime::currentDateTime();
    for (Meter *meter : m_meters)
    {
        m_lastSampleTime[meter->meterId()] = now;
    }

    Logger::instance()->log(LogLevel::Info,
                            QString("BusPollerThread: 总线 %1 轮询线程创建，电表数量: %2").arg(busId).arg(meters.size()));
}

BusPollerThread::~BusPollerThread()
{
    stopPolling();
    wait();

    // 清理Modbus主站（在工作线程中创建的）
    if (m_modbusMaster)
    {
        delete m_modbusMaster;
        m_modbusMaster = nullptr;
    }

    Logger::instance()->log(LogLevel::Info,
                            QString("BusPollerThread: 总线 %1 轮询线程销毁").arg(m_busId));
}

// 设置轮询间隔
void BusPollerThread::setPollInterval(int interval)
{
    m_pollInterval = interval;
}

// 停止轮询
void BusPollerThread::stopPolling()
{
    m_running = false;
}

// 运行轮询
void BusPollerThread::run()
{
    m_running = true;

    Logger::instance()->log(LogLevel::Info,
                            QString("BusPollerThread: 总线 %1 开始轮询").arg(m_busId));

    // 检查串口是否已设置
    if (!m_serialPort)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("BusPollerThread: 总线 %1 串口未设置").arg(m_busId));
        return;
    }

    // 在工作线程中创建Modbus主站
    // 注意：不移动串口，ModbusMaster内部使用互斥锁保护串口访问
    m_modbusMaster = new ModbusMaster(m_serialPort);

    Logger::instance()->log(LogLevel::Info,
                            QString("BusPollerThread: 总线 %1 Modbus主站已创建").arg(m_busId));

    while (m_running)
    {
        int successCount = 0;
        int totalCount = m_meters.size();
        m_updatedMeterIds.clear(); // 清空本轮更新列表

        // 轮询每个电表
        for (Meter *meter : m_meters)
        {
            if (!m_running)
            {
                break;
            }

            // 读取电表数据
            ModbusMaster::ModbusResponse response =
                m_modbusMaster->readMeterData(meter->meterId());

            if (response.success)
            {
                // 更新电表数据
                meter->updateFromRegisters(response.data);
                m_updatedMeterIds.append(meter->meterId()); // 记录已更新的电表ID
                successCount++;

                // 检查是否需要采样存储（每5分钟）
                QDateTime now = QDateTime::currentDateTime();
                QDateTime lastSample = m_lastSampleTime.value(meter->meterId(), now);
                qint64 secondsSinceLastSample = lastSample.secsTo(now);

                // 5分钟 = 300秒
                if (secondsSinceLastSample >= 300)
                {
                    // 发送采样信号
                    emit meterDataSampled(meter->meterId(), meter);
                    m_lastSampleTime[meter->meterId()] = now;

                    Logger::instance()->log(LogLevel::Debug,
                                            QString("BusPollerThread: 总线 %1，电表 %2 数据采样")
                                                .arg(m_busId)
                                                .arg(meter->meterId()));
                }
            }
            else
            {
                // 标记电表离线
                meter->setOnline(false);
                Logger::instance()->log(LogLevel::Warning,
                                        QString("BusPollerThread: 总线 %1，电表 %2 读取失败: %3")
                                            .arg(m_busId)
                                            .arg(meter->meterId())
                                            .arg(response.errorMessage));
            }

            // 避免过快轮询，每个电表之间间隔15ms（增加间隔避免冲突）
            QThread::msleep(15);
        }

        // 发送批量更新信号（一次性通知所有更新）
        if (!m_updatedMeterIds.isEmpty())
        {
            emit meterDataBatchUpdated(m_updatedMeterIds);
        }

        // 发送轮询周期完成信号
        emit pollCycleCompleted(m_busId, successCount, totalCount);

        Logger::instance()->log(LogLevel::Debug,
                                QString("BusPollerThread: 总线 %1 轮询完成: %2/%3").arg(m_busId).arg(successCount).arg(totalCount));

        // 等待下一个轮询周期
        QThread::msleep(m_pollInterval);
    }

    // 清理Modbus主站
    if (m_modbusMaster)
    {
        delete m_modbusMaster;
        m_modbusMaster = nullptr;
    }

    Logger::instance()->log(LogLevel::Info,
                            QString("BusPollerThread: 总线 %1 停止轮询").arg(m_busId));
}

// ============================================================================
// PollScheduler 实现
// ============================================================================

PollScheduler::PollScheduler(SerialPortManager *portManager, QObject *parent)
    : QObject(parent), m_portManager(portManager), m_pollInterval(500), m_polling(false)
{
    Logger::instance()->log(LogLevel::Info, "PollScheduler: 轮询调度器初始化");
}

PollScheduler::~PollScheduler()
{
    // 1. 先停止所有轮询（确保线程不再访问串口，并清理所有线程对象）
    stopPolling();

    // 注意：串口对象由 SerialPortManager 管理，这里不删除
    // 注意：线程对象已在 stopPolling() 中清理
    Logger::instance()->log(LogLevel::Info, "PollScheduler: 轮询调度器销毁");
}

// 添加总线
bool PollScheduler::addBus(int busId, const QString &portName, const QVector<Meter *> &meters)
{
    if (m_busThreads.contains(busId))
    {
        Logger::instance()->log(LogLevel::Info,
                                QString("PollScheduler: 总线 %1 已存在，跳过").arg(busId));
        return true; // 已存在视为成功
    }

    if (meters.isEmpty())
    {
        Logger::instance()->log(LogLevel::Warning,
                                QString("PollScheduler: 总线 %1 没有电表").arg(busId));
        return false;
    }

    // 获取串口（仅借用，不管理生命周期）
    QSerialPort *port = m_portManager->getPort(portName);
    if (!port)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("PollScheduler: 总线 %1: 串口 %2 不存在").arg(busId).arg(portName));
        return false;
    }

    if (!port->isOpen())
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("PollScheduler: 总线 %1: 串口 %2 未打开").arg(busId).arg(portName));
        return false;
    }

    // 创建轮询线程（串口将在线程启动时移动到工作线程）
    BusPollerThread *thread = new BusPollerThread(busId, port, meters, this);
    thread->setPollInterval(m_pollInterval);
    m_busThreads.insert(busId, thread);

    // 连接信号
    connect(thread, &BusPollerThread::pollCycleCompleted,
            this, &PollScheduler::onPollCycleCompleted);
    connect(thread, &BusPollerThread::meterDataBatchUpdated,
            this, &PollScheduler::meterDataBatchUpdated);
    connect(thread, &BusPollerThread::meterDataSampled,
            this, &PollScheduler::meterDataSampled);

    Logger::instance()->log(LogLevel::Info,
                            QString("PollScheduler: 添加总线 %1: 串口=%2, 电表数=%3")
                                .arg(busId)
                                .arg(portName)
                                .arg(meters.size()));

    return true;
}

// 设置轮询间隔
void PollScheduler::setPollInterval(int interval)
{
    m_pollInterval = interval;

    // 更新所有线程的轮询间隔
    for (BusPollerThread *thread : m_busThreads)
    {
        thread->setPollInterval(interval);
    }
}

// 启动轮询
void PollScheduler::startPolling()
{
    if (m_polling)
    {
        Logger::instance()->log(LogLevel::Warning, "PollScheduler: 轮询已经启动");
        return;
    }

    if (m_busThreads.isEmpty())
    {
        Logger::instance()->log(LogLevel::Error, "PollScheduler: 没有配置总线");
        return;
    }

    // 启动所有轮询线程
    for (BusPollerThread *thread : m_busThreads)
    {
        thread->start();
    }

    m_polling = true;
    emit pollingStarted();

    Logger::instance()->log(LogLevel::Info,
                            QString("PollScheduler: 轮询调度器启动，总线数: %1").arg(m_busThreads.size()));
}

// 停止轮询
void PollScheduler::stopPolling()
{
    if (!m_polling)
    {
        return;
    }

    // 停止所有轮询线程
    for (BusPollerThread *thread : m_busThreads)
    {
        thread->stopPolling();
    }

    // 等待所有线程结束
    for (BusPollerThread *thread : m_busThreads)
    {
        thread->wait();
    }

    // 删除所有线程对象并清空映射表
    for (BusPollerThread *thread : m_busThreads)
    {
        delete thread;
    }
    m_busThreads.clear();

    m_polling = false;
    emit pollingStopped();

    Logger::instance()->log(LogLevel::Info, "PollScheduler: 轮询调度器停止，所有总线线程已清理");
}

// 处理总线轮询周期完成
void PollScheduler::onPollCycleCompleted(int busId, int successCount, int totalCount)
{
    emit busPollCompleted(busId, successCount, totalCount);
}
